<template>
  <div class="print-render-content">
    <div style="position: relative" v-loading="loading" class="print-render-pages-content">
      <template v-for="pageLayout in printLayout" :key="pageLayout?.layoutId">
        <JnpfUniverPrintRenderPage
          :jnpf-univer-api="props.jnpfUniverApi"
          :page-layout="pageLayout"
          :print-config="printConfig"
          @rendered="handlePageRendered" />
      </template>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { reactive, toRefs } from 'vue';
  import { buildUUID } from '../../Design/univer/utils/uuid';

  import { getPrintPageStyle } from '../../Design/univer/utils';
  import { JnpfPrintPageInfo } from '../../Design/univer/utils/define';

  import JnpfUniverPrintRenderPage from './Page/index.vue';
  import { JnpfSheetsPrintUiService } from '../../Design/univer/services/sheet-print-ui.service';

  defineOptions({ name: 'JnpfUniverPrint' });

  const props = defineProps(['jnpfUniverApi']);

  interface State {
    loading: boolean;

    printLayout: any[];
    printStyle: any;
    printConfig: any;

    pageRenderedQuantity: number;
  }
  const state = reactive<State>({
    loading: false,

    printLayout: [],
    printStyle: null,
    printConfig: null,

    pageRenderedQuantity: 0,
  });
  const { loading, printLayout, printConfig } = toRefs(state);

  // 处理页面已渲染，主要是知道页面是不是都渲染完了
  function handlePageRendered() {
    state.pageRenderedQuantity += 1;

    if (state.printLayout?.length === state.pageRenderedQuantity) {
      state.loading = false;
    }
  }

  // 暴露 - 处理打印渲染
  function handlePrintRender(printConfig: any) {
    resetState();

    state.loading = true;
    state.printConfig = { ...printConfig };

    // 这里待优化
    const { jnpfUniverApi } = props ?? {};

    jnpfUniverApi?.getSheetsPrint()?.updateLayoutConfig({
      area: printConfig.area,
      paperSize: printConfig.paperSize,
      direction: printConfig.direction,
      scale: printConfig.scale,
      WorkbookTitleText: printConfig.WorkbookTitleText,
    });

    const headerFooter: any[] = [];
    if (printConfig?.Time) {
      headerFooter.push(JnpfPrintPageInfo.Time);
    }
    if (printConfig?.Date) {
      headerFooter.push(JnpfPrintPageInfo.Date);
    }
    if (printConfig?.WorkbookTitle) {
      headerFooter.push(JnpfPrintPageInfo.WorkbookTitle);
    }
    if (printConfig?.WorksheetTitle) {
      headerFooter.push(JnpfPrintPageInfo.WorksheetTitle);
    }
    if (printConfig?.PageSize) {
      headerFooter.push(JnpfPrintPageInfo.PageSize);
    }

    jnpfUniverApi?.getSheetsPrint()?.updateRenderConfig({
      gridlines: printConfig.gridlines,
      hAlign: printConfig.hAlign,
      vAlign: printConfig.vAlign,
      headerFooter: headerFooter,
    });

    jnpfUniverApi?.getSheetsPrint()?.reLayout();
    const config = jnpfUniverApi.getSheetsPrint()?.getSetting();

    if (!config) {
      return;
    }

    const { infos, layout } = config;
    let num = 1;
    const pages = infos
      .map((info: any) =>
        info.pages.map((range: any, index: number) => {
          const config = { page: num++, ...info, range, subPage: index };
          return {
            config,
            page: config.page,
            previewScale: 1,
            layoutId: `layout_${buildUUID()}`,
          };
        }),
      )
      .flat();

    state.printLayout = Array.isArray(pages) ? [...pages] : [];

    const { direction, paperSize } = layout;
    state.printStyle = getPrintPageStyle(paperSize, direction);
  }

  // 暴露 - 浏览器打印
  function handleBrowserPrint() {
    const { jnpfUniverApi } = props ?? {};

    const print = document.createElement('div');
    print.id = 'jnpfReportPrint';
    const injector = jnpfUniverApi?.getSheets()?.getInjector();
    const pageSize = jnpfUniverApi?.getSheetsPrint()?.getPaperSize();
    const canvasList = state.printLayout?.map((page: any) => {
      const { config } = page;
      const canvas = new JnpfSheetsPrintUiService(injector, config, false);
      canvas.container.style.width = '100%';
      canvas.container.style.height = '100%';
      return canvas;
    });
    canvasList.forEach((canvas: any, index: number) => {
      if (state.printLayout?.[index]) {
        const { previewScale } = state.printLayout[index];
        const pageDiv = document.createElement('div');
        pageDiv.className = 'printContainer';
        const scale = Math.round(previewScale * (794 / pageSize.w) * 10) / 10;
        pageDiv.style.width = pageSize.w * scale + 'px';
        pageDiv.style.height = pageSize.h * scale + 'px';
        pageDiv.appendChild(canvas.container);
        print.appendChild(pageDiv);
      } else {
        print.appendChild(canvas.container);
      }
    });
    document.head.appendChild(state.printStyle);
    document.body.appendChild(print);
    setTimeout(() => {
      window.onbeforeprint = () => {
        canvasList.forEach((canvas: any, index: number) => {
          if (state.printLayout[index]) {
            const { config } = state.printLayout[index];
            canvas.updateConfig(config);
          }
          canvas.render();
          canvas.renderOnReady();
        });
      };
      window.onafterprint = () => {
        canvasList.forEach((canvas: any) => {
          canvas.dispose();
        });
        document.head.removeChild(state.printStyle);
        document.body.removeChild(print);
      };
      window.print();
    }, 100);
  }

  // 暴露 - 重置
  function resetState() {
    state.loading = false;

    state.printLayout = [];
    state.printStyle = null;
    state.printConfig = null;

    state.pageRenderedQuantity = 0;
  }

  defineExpose({ handlePrintRender, handleBrowserPrint, resetState });
</script>

<style lang="less">
  .print-render-content {
    flex: 1;
    overflow: auto;
    display: flex;

    .print-render-pages-content {
      flex: 1;
      overflow: auto;
    }
  }
</style>
